import { baseURL } from './config.js'

const DEFAULT_MAX_RETRY = 5
const QUEUE_TIMEOUT = 1000 * 60 * 2 // 2 分钟
const MAX_QUEUE_LENGTH = 50
const MAX_CONCURRENT = 3 // 同时重发请求数

let failedQueue = []
let loadingShown = false
let activeQueueCount = 0
let isRedirectingToLogin = false

const delay = ms => new Promise(resolve => setTimeout(resolve, ms))

function getHttp() {
	if (!uni.$u || !uni.$u.http) throw new Error('uView 未挂载，uni.$u.http 不存在')
	return uni.$u.http
}

export function setBaseURL() {
	getHttp().setConfig(config => {
		config.baseURL = baseURL
		return config
	})
}

async function isNetworkAvailable() {
	return new Promise(resolve => {
		uni.getNetworkType({
			success: res => resolve(res.networkType !== 'none'),
			fail: () => resolve(false)
		})
	})
}

function showNetworkLoading() {
	if (!loadingShown) {
		loadingShown = true
		uni.showLoading({
			title: '网络不可用，等待重连...',
			mask: true
		})
	}
}

function hideNetworkLoading() {
	if (loadingShown) {
		loadingShown = false
		uni.hideLoading()
	}
}

function saveQueue() {
	try {
		uni.setStorageSync('failedQueue', JSON.stringify(failedQueue))
	} catch (e) {
		console.warn('队列保存失败', e)
	}
}

function loadQueue() {
	try {
		const data = uni.getStorageSync('failedQueue')
		if (data) failedQueue = JSON.parse(data)
	} catch (e) {
		console.warn('队列加载失败', e)
		failedQueue = []
	}
}

// 🔹 统一登录跳转 + 弹框
function redirectToLogin() {
	if (isRedirectingToLogin) return
	isRedirectingToLogin = true

	uni.showModal({
		title: '请登录',
		showCancel: false,
		success: () => {
			uni.navigateTo({ url: '/pages/login/index' })
		},
		complete: () => {
			setTimeout(() => { isRedirectingToLogin = false }, 1000)
		}
	})
}

function generateUUID() {
	const hex = () => Math.floor(Math.random() * 16).toString(16)
	return (
		hex() + hex() + hex() + hex() + '-' +
		hex() + hex() + '-' +
		hex() + hex() + '-' +
		hex() + hex() + '-' +
		hex() + hex() + hex() + hex() + hex() + hex()
	)
}

// 🔹 队列重发调度
async function processQueue() {
	if (activeQueueCount >= MAX_CONCURRENT) return
	if (!failedQueue.length) return

	const slot = Math.min(MAX_CONCURRENT - activeQueueCount, failedQueue.length)
	for (let i = 0; i < slot; i++) {
		const { options, resolve, reject, time } = failedQueue.shift()
		activeQueueCount++
		if (Date.now() - time > QUEUE_TIMEOUT) {
			reject(new Error('请求因超时未发送'))
			activeQueueCount--
			continue
		}
		request(options)
			.then(data => resolve(data))
			.catch(err => reject(err))
			.finally(() => {
				activeQueueCount--
				processQueue() // 处理下一个
			})
	}
	saveQueue()
}

uni.onNetworkStatusChange(async res => {
	if (res.isConnected) {
		hideNetworkLoading()
		processQueue()
	} else {
		showNetworkLoading()
	}
})

export async function request(options) {
	const http = getHttp()
	const networkOk = await isNetworkAvailable()
	if (!networkOk) {
		return new Promise((resolve, reject) => {
			if (failedQueue.length >= MAX_QUEUE_LENGTH) {
				reject(new Error('请求队列已满'))
				return
			}
			failedQueue.push({ options, resolve, reject, time: Date.now() })
			saveQueue()
			showNetworkLoading()
		})
	}

	const maxRetry = options.maxRetry ?? DEFAULT_MAX_RETRY
	const enableRetry = options.retryable ?? true
	const onError = options.onError

	options.header = options.header || {}
	const token = uni.getStorageSync('token')
	if (token) options.header.Authorization = `Bearer ${token}`

	if (!options._idempotencyKey) options._idempotencyKey = generateUUID()
	options.header['Idempotency-Key'] = options._idempotencyKey

	if (typeof options._retryCount === 'undefined') options._retryCount = 0

	try {
		const res = await http.request(options)

		// 🔹 HTTP 层 401
		if (res.statusCode === 401) {
			redirectToLogin()
			return Promise.reject({ code: 401, message: '未登录' })
		}

		// 🔹 业务层状态码
		if (res.data.code === 200) return res.data
		else if (res.data.code === 401) {
			redirectToLogin()
			return Promise.reject({ code: 401, message: '未登录' })
		} else {
			if (onError) onError(res.data)
			else uni.showToast({ title: res.data.message || '请求失败', icon: 'none' })
			return Promise.reject(res.data)
		}
	} catch (err) {
		const status = err?.statusCode ?? err?.response?.statusCode ?? 0

		if (status === 401) {
			redirectToLogin()
			return Promise.reject({ code: 401, message: '未登录' })
		}

		const retryableError =
			enableRetry &&
			(status === 0 ||
				status >= 500 ||
				status === 429 ||
				(err?.errMsg || '').includes('timeout') ||
				(err?.errMsg || '').includes('Network'))

		if (retryableError && options._retryCount < maxRetry) {
			options._retryCount++
			options._isRetry = true
			const waitTime = Math.pow(2, options._retryCount - 1) * 500
			if (import.meta.env.MODE === 'development') {
				console.log(`请求失败，${waitTime}ms 后重试（第 ${options._retryCount} 次）`, options)
			}
			await delay(waitTime)
			return request(options)
		}

		if (onError) onError(err)
		else uni.showToast({ title: '网络异常，请稍后再试', icon: 'none' })

		return Promise.reject(err)
	}
}

// 🔹 get/post 封装
export const get = (url, data, config = {}) =>
	request({ url, method: 'GET', data, ...config })

export const post = (url, data, config = {}) =>
	request({ url, method: 'POST', data, ...config })

// 🔹 初始化队列
loadQueue()
processQueue()